using System;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Security;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Xsl;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.WebPartPages.Communication;
using Mvp.Xml.Exslt;
using PS.WebParts.Rollup;
using PS.WebParts.Rollup.Core;
using MenuItem=Microsoft.SharePoint.WebPartPages.MenuItem;

namespace PS.WebParts
{
    [XmlRoot(Namespace = "PS.WebParts"), ToolboxData("<{0}:RollUp runat=server></{0}:RollUp>")]
    public class RollUp : RollUpWebPart
    {
        public string TopLevelSite
        {
            get
            {
                return base.TopLevel;
            }
            set
            {
                base.TopLevel = value;
            }
        }
    }
    
    [XmlRoot(Namespace = "PS.WebParts.Rollup"), ToolboxData("<{0}:RollUpWebPart runat=server></{0}:RollUpWebPart>")]
    public class RollUpWebPart : WebPart, ICellConsumer, ICellProvider
    {
        RollUpDataSource _dsv;
        
        // Events
        public event CellConsumerInitEventHandler CellConsumerInit;
        public event CellProviderInitEventHandler CellProviderInit;
        public event CellReadyEventHandler CellReady;

        // Fields
        /*
                private const string a_var = "";
        */
        private string viewStateProvider;

        private CellConsumerInitEventHandler ab = null;
        private CellProviderInitEventHandler ad = null;
        private CellReadyEventHandler ae = null;

        private int ac;

        //private SPSite site;
        private string xsl;
        //private string pQuery;
       // private bool m;
        private bool doDebug;
        private bool doDebugQuery;
        private string debugContextInfo;
        //private string w;
        private TextBox textBox;
        private readonly string fieldName;
        private string cellProviderSiteUrl;
        


        protected RollUpDataSource DSView
        {
            get
            {
                if (_dsv == null)
                {
                   _dsv = new  RollUpDataSource();
                }
                return _dsv;
            }
        }
        
        public RollUpWebPart()
        {
            this.xsl = "";
            this.doDebug = false;
            this.doDebugQuery = false;
            this.debugContextInfo = "";
            //this.w = "";
            this.fieldName = "Cell Data";
            this.cellProviderSiteUrl = "";
            this.viewStateProvider = "";
            this.ac = 0;
            base.Load += new EventHandler(this.ProcessPostBack);
        }


        /*
                private SPWeb GetWeb()
                {
                    SPWeb web2 = SPControl.GetContextWeb(base.Context);
                    SPWeb web1 = web2;
                    while (!web1.IsRootWeb)
                    {
                        web1 = web1.ParentWeb;
                    }
                    return web1;
                }
        */



        /*
                private static string ConvertDate(Match A_0)
                {
                    string text1 = A_0.Groups[1].ToString();
                    DateTime time1 = DateTime.Parse(RollUpWebPart.c());
                    time1 = time1.AddDays(Convert.ToDouble(text1));
                    return SPUtility.CreateISO8601DateTimeFromSystemDateTime(time1);
                }
        */


        private void TextChanged(object o, EventArgs e)
        {
        }


        private void WriteException(HtmlTextWriter writer, Exception exception)
        {
            writer.Write("<font color=red><b>ERROR:</b><br>");
            writer.Write(exception.Message);
            writer.Write("<br>");
            writer.Write(exception.StackTrace);
            if (this.debugContextInfo != "")
            {
                writer.Write("<br><b>Debug Info</b></br>");
                writer.Write(this.debugContextInfo);
            }
            writer.Write("</font>");
        }


        /*
                private void Write(HtmlTextWriter A_0, string A_1)
                {
                    A_0.Write("<font color=blue>" + A_1 + "</font><br>");
                }
        */

        private void GetDebugContextInfo(SPWeb web)
        {
            string rootUrl = web.Url;
            string portalUrl = web.PortalUrl;
            string serverRelativeUrl = web.ServerRelativeUrl;
            
            StringBuilder sb = new StringBuilder(128);
            sb.Append("<br/> Effective Url: " + rootUrl);
            sb.Append("<br/> PortalUrl: " + portalUrl);
            sb.Append("<br/> RelativeUrl: " + serverRelativeUrl);
            sb.Append("<br/> Top Level Setting: " + this.TopLevel);
            this.debugContextInfo = sb.ToString();
            
            //if (portalUrl != serverRelativeUrl && serverRelativeUrl != "/")
            //{
            //    rootUrl = rootUrl.Replace(web.ServerRelativeUrl, "");
            //}
            //this.debugContextInfo = this.debugContextInfo + "<br/>Url2:" + rootUrl;
            return;
        }



        private void ProcessPostBack(object o, EventArgs eventArgs)
        {
            if (this.Page.IsPostBack)
            {
                string text1 = this.Page.Request["__EVENTARGUMENT"];
                string text2 = this.Page.Request["__EVENTTARGET"];
                if ((text1 != null) && (text2 == this.ID))
                {
                    this.viewStateProvider = SPEncode.HtmlDecode(text1);
                    this.ViewState["RollUpProvideValue"] = this.viewStateProvider;
                }
                else
                {
                    this.viewStateProvider = (string)this.ViewState["RollUpProvideValue"];
                }
            }
        }


        private void WriteError(HtmlTextWriter writer, string message)
        {
            writer.Write("<font color=red>" + message + "</font><br>");
        }


        //private static string c()
        //{
        //    return RollUpWebPart.ag;
        //}

        public override ConnectionRunAt CanRunAt()
        {
            return ConnectionRunAt.Server;
        }

        protected override void CreateChildControls()
        {
            this.textBox = new TextBox();
            this.textBox.TextChanged += new EventHandler(this.TextChanged);
            this.textBox.AutoPostBack = true;
            this.textBox.Attributes.Add("style", "width: 0px; height: 0px; display: none; visibility: hidden");
            this.textBox.Text = this.viewStateProvider;
            this.Controls.Add(this.textBox);
        }

        public override void CreateWebPartMenu()
        {
            base.WebPartMenu.MenuItems.Add(new MenuItem("www.portalsolutions.net", "javascript:{var win = window.open('http://www.portalsolutions.net');}"));
            base.CreateWebPartMenu();
        }


        public override void EnsureInterfaces()
        {
            try
            {
                base.RegisterInterface("RollUpCellConsumer", "ICellConsumer", -1, ConnectionRunAt.Server, this, "", "Consumes a cell from", "Consumes a cell of data");
                base.RegisterInterface("RollUpCellProvider", "ICellProvider", -1, ConnectionRunAt.Server, this, "", "Provides a cell to", "Provides a cell of data");
            }
            catch (SecurityException)
            {
            }
        }

        public override InitEventArgs GetInitEventArgs(string interfaceName)
        {
            if (interfaceName == "RollUpCellConsumer")
            {
                this.EnsureChildControls();
                CellConsumerInitEventArgs args1 = new CellConsumerInitEventArgs();
                args1.FieldName = this.fieldName;
                return args1;
            }
            return null;
        }


        public override ToolPart[] GetToolParts()
        {
            ToolPart[] partArray1 = new ToolPart[3];
            WebPartToolPart part1 = new WebPartToolPart();
            CustomPropertyToolPart part2 = new CustomPropertyToolPart();
            partArray1[0] = part2;
            partArray1[1] = part1;
            partArray1[2] = new RollUpToolpart();
            return partArray1;
        }


        void ICellConsumer.CellProviderInit(object sender, CellProviderInitEventArgs cellProviderInitArgs)
        {
        }


        void ICellConsumer.CellReady(object sender, CellReadyEventArgs cellReadyArgs)
        {
            if (cellReadyArgs.Cell != null)
            {
                this.cellProviderSiteUrl = cellReadyArgs.Cell.ToString();
            }
        }

        void ICellProvider.CellConsumerInit(object sender, CellConsumerInitEventArgs cellConsumerInitArgs)
        {
        }

        public override void PartCommunicationConnect(string interfaceName, WebPart connectedPart, string connectedInterfaceName, ConnectionRunAt runAt)
        {
            this.EnsureChildControls();
            if (interfaceName == "RollUpCellConsumer")
            {
                this.ac++;
            }
        }
        public override void PartCommunicationInit()
        {
            if ((this.ac > 0) && (this.ab != null))
            {
                CellConsumerInitEventArgs args1 = new CellConsumerInitEventArgs();
                args1.FieldName = this.fieldName;
                this.ab(this, args1);
            }
            if (this.ad != null)
            {
                CellProviderInitEventArgs args2 = new CellProviderInitEventArgs();
                args2.FieldName = this.fieldName;
                this.ad(this, args2);
            }
        }

        public override void PartCommunicationMain()
        {
            if (this.ae != null)
            {
                CellReadyEventArgs args1 = new CellReadyEventArgs();
                args1.Cell = SPEncode.HtmlEncode(this.viewStateProvider);
                this.ae(this, args1);
            }
        }
        protected override void RenderWebPart(HtmlTextWriter output)
        {
            this.EnsureChildControls();
            this.textBox.RenderControl(output);
            DataSet dsData;
            WebInfo webInfo = null;
            try
            {
                
                //SPControl.GetContextWeb(this.Context);
                //SPSite site1 = SPControl.GetContextSite(this.Context);
                //string text4 = site1.RootWeb.Url;
                
                string topLevel = this.TopLevel;
                SPWeb spWeb;
                
                if (string.IsNullOrEmpty(topLevel))
                {
                    spWeb = SPControl.GetContextWeb(base.Context);
                }
                else
                {
                    webInfo = ARollupDataSourceView.GetWeb(topLevel, base.Context);
                    spWeb = webInfo.Web;
                }
                
                this.GetDebugContextInfo(spWeb);
                //string text5 = site1.HostName;
                //output.Write(topLevel+":");
                
                if ( !string.IsNullOrEmpty(topLevel) )
                {
                    if (topLevel == "[CellProvider]" && !string.IsNullOrEmpty( this.cellProviderSiteUrl ))
                    {
                        webInfo  = ARollupDataSourceView.GetWeb(this.cellProviderSiteUrl, base.Context);
                        spWeb = webInfo.Web;
                    }
                }
                
                
                if ((this.Lists == null) || (this.Fields == null))
                {
                    this.WriteError(output, "Warning: Check RollUpWebPart properties");
                }
                else if (spWeb != null)
                {
                    RollUpDataSource view = DSView;
                    DataTable table = view.GetRollUpData(spWeb);
                    DataSet ds = table.DataSet; 
                    if (ds == null) 
                    {
                        ds = new DataSet("Rows");
                        ds.Tables.Add(table);
                    }
                    dsData = ds;

                    //string text2 = this.b_var.GetXml();
                    //this.u = text2;
                    if (this.doDebug)
                    {
                        string messages = view.ProcessingMessages;
                        if (messages != null)
                        {
                            output.Write("<font color=red>DEBUG</font><br><font color=blue>");
                            output.Write("<pre>" + messages.Replace("\n", "<br />") + "</pre>");
                            output.Write("</font><br>");
                        }
                        
                        output.Write("<font color=red>DEBUG XML</font><br><font color=blue>");
                        output.Write("<pre>" + SPEncode.HtmlEncode(dsData.GetXml()) + "</pre>");
                        output.Write("</font><br>");
                    }
                    if (this.doDebugQuery)
                    {
                        output.Write("<font color=red>DEBUG CAML Query</font><br><font color=blue>");
                        output.Write("<pre>" + SPEncode.HtmlEncode(view.Query) + "</pre>");
                        output.Write("</font><br>");
                    }
                    if (this.xsl != "")
                    {
                        this.xsl = this.xsl.Replace("__doPostBack(''", "__doPostBack('" + this.ID + "'");
                        this.xsl = this.xsl.Replace("[CellProvider]", this.viewStateProvider);
                        this.xsl = this.xsl.Replace("[CellConsumer]", this.cellProviderSiteUrl);
                        XmlTextReader reader1 = new XmlTextReader(new StringReader(this.xsl));
                        ExsltTransform transform1 = new ExsltTransform();
                        transform1.Load(reader1, null);
                        XmlDataDocument document1 = new XmlDataDocument(dsData);
                        StringWriter writer1 = new StringWriter();
                        XmlTextWriter writer2 = new XmlTextWriter(writer1);
                        double page = 0;
                        if (this.Page.Request.QueryString["page"] != null)
                        {
                            page = double.Parse(this.Page.Request.QueryString["page"]);
                        }
                        XsltArgumentList xsltArgumentList = new XsltArgumentList();
                        xsltArgumentList.AddParam("CurrentPage", string.Empty, page);
                        xsltArgumentList.AddParam("RecordCount", string.Empty, dsData.Tables["Row"].Rows.Count);
                        transform1.SupportedFunctions = ExsltFunctionNamespace.All;
                        transform1.MultiOutput = false;
                        transform1.Transform(document1, xsltArgumentList, writer2);
                        string text3 = writer1.ToString();
                        text3 = text3.Replace("&lt;", "<");
                        text3 = text3.Replace("&gt;", ">");
                        output.Write(text3);
                    }
                    else
                    {
                        this.WriteError(output, "Warning: Need a XSL to render data");
                    }
                }
            }
            catch (Exception exception1)
            {
                this.WriteException(output, exception1);
                //this.WriteError(output, this.w);
            }
            finally
            {
                if (webInfo != null)
                    webInfo.Dispose();
            }
            //if (this.w.Length > 0)
            //{
            //    this.WriteError(output, this.w);
            //}
            if (( ! string.IsNullOrEmpty( this.debugContextInfo )) && this.doDebug)
            {
                this.WriteError(output, this.debugContextInfo);
            }
        }


        [DefaultValue(false), Category("RollUp"), WebPartStorage(Storage.Personal), FriendlyName("Dates in ISO8601"), Description("Dates in ISO8601"), Browsable(true)]
        public bool DateISO8601
        {
            get
            {
                return DSView.DatesInISO8601;
            }
            set
            {
                DSView.DatesInISO8601 = value;
            }
        }

        [FriendlyName("Debug XML"), Category("RollUp"), DefaultValue(false), WebPartStorage(Storage.Personal), Browsable(true), Description("Show XML")]
        public bool Debug
        {
            get
            {
                return this.doDebug;
            }
            set
            {
                this.doDebug = value;
            }
        }

        [Obsolete, FriendlyName("Obsolete"), Category(""), DefaultValue(false), WebPartStorage(Storage.Personal), Browsable(false), Description("use [QS:]")]
        public bool EnableQueryStringFilter
        {
            get
            {
                return false;
            }
            set
            { }
        }

        [Description("Debug Query"), Browsable(true), Category("RollUp Query"), DefaultValue(false), WebPartStorage(Storage.Personal), FriendlyName("Debug Query")]
        public bool DebugQuery
        {
            get
            {
                return this.doDebugQuery;
            }
            set
            {
                this.doDebugQuery = value;
            }
        }
        [WebPartStorage(Storage.Personal), Description("Fields Names field,field, ..."), Category("RollUp"), DefaultValue(""), Browsable(true), FriendlyName("Fields")]
        public string Fields
        {
            get
            {
                FieldInfoCollection list = DSView.GetFields();

                StringBuilder sb = new StringBuilder();
                if (list.Count == 0)
                    return null;

                bool first = true;
                foreach (FieldInfo info in list)
                {
                    if (!first)
                        sb.Append(',');
                    sb.Append(info.InternalName);
                    first = false;
                }
                return sb.ToString();
            }
            set
            {
               DSView.SetListFieldNames( value );
            }
        }
        [Browsable(true), Description("Fix Lookups"), Category("RollUp"), DefaultValue(false), WebPartStorage(Storage.Personal), FriendlyName("Fix Lookups")]
        public bool FixLookups
        {
            get
            {
                return DSView.FixLookups;
            }
            set
            {
                DSView.FixLookups = value;
            }
        }

        [Category("RollUp"), FriendlyName("Include List data"), Browsable(true), Description("Include the list data underscore fields"), DefaultValue(false), WebPartStorage(Storage.Personal)]
        public bool IncludeData
        {
            get
            {
                return DSView.IncludeListData;
            }
            set
            {
                DSView.IncludeListData = value;
            }
        }

        [Browsable(true), WebPartStorage(Storage.Personal), Category("RollUp"), DefaultValue(""), FriendlyName("Lists"), Description("Lists to rollup format /site/subsite:List,/site/subsite/List")]
        public string Lists
        {
            get
            {
                return DSView.Lists;
            }
            set
            {
                DSView.Lists = value;
            }
        }

        //[Description(""), FriendlyName("Page Query String (ID)"), Browsable(false), Category("RollUp"), DefaultValue(""), WebPartStorage(Storage.Personal)]
        //public string PageQueryString
        //{
        //    get
        //    {
        //        return DSView.PageQueryString;
        //    }
        //    set
        //    {
        //        DSView.PageQueryString = value;
        //    }
        //}

        [FriendlyName("CAML Query"), DefaultValue(""), WebPartStorage(Storage.Personal), Description("CAML Query"), Browsable(true), Category("RollUp Query")]
        public string Query
        {
            get
            {
                return DSView.Query;
            }
            set
            {
                DSView.Query = value;
            }
        }

        [DefaultValue(false), Description("Query Moderator"), Browsable(true), Category("RollUp Query"), WebPartStorage(Storage.Personal), FriendlyName("Query Moderator")]
        public bool QueryModerator
        {
            get
            {
                return DSView.QueryModerator;
            }
            set
            {
                DSView.QueryModerator = value;
            }
        }

        [WebPartStorage(Storage.Personal), Browsable(true), DefaultValue(false), Category("RollUp Query"), FriendlyName("Query Recursive"), Description("Query Recursive")]
        public bool QueryRecursive
        {
            get
            {
                return DSView.QueryRecursive;
            }
            set
            {
                DSView.QueryRecursive = value;
            }
        }

        [FriendlyName("CAML Query RowLimit"), Category("RollUp Query"), DefaultValue(""), WebPartStorage(Storage.Personal), Browsable(true), Description("CAML Query RowLimit")]
        public string QueryRowLimit
        {
            get
            {
                return DSView.QueryRowLimit;
            }
            set
            {
                DSView.QueryRowLimit = value;
            }
        }

        [Description("Rollup the content of lists list,list in all subsites"), Category("RollUp"), WebPartStorage(Storage.Personal), DefaultValue(false), Browsable(true), FriendlyName("Lists in all SubSites")]
        public bool SubSites
        {
            get
            {
                return DSView.Scope != RollUpQueryWebScope.Web;
            }
            set
            {
                DSView.Scope = value ? RollUpQueryWebScope.Recursive : RollUpQueryWebScope.Web;
            }
        }

        [FriendlyName("From Top Level"), Description(""), Browsable(true), Category("RollUp"), DefaultValue(""), WebPartStorage(Storage.Personal)]
        public string TopLevel
        {
            get
            {
                return DSView.TopLevelSite;
            }
            set
            {
                DSView.TopLevelSite = value;
            }
        }

        [FriendlyName("XSL"), WebPartStorage(Storage.Personal), Description("XSL to render RollUp"), Browsable(true), Category("RollUp Presentation"), DefaultValue("")]
        public string XSL
        {
            get
            {
                return this.xsl;
            }
            set
            {
                this.xsl = value;
            }
        }


    }

}
